
#ifndef RTHTTPINTERFACE_H
#define RTHTTPINTERFACE_H

#include "RtDefines.h"
#include "RtError.h"
#include "RtReferenceControl.h"
#include "RtConnectionInterface.h"

class IRtChannel;
  class IRtChannelHttpClient;
  class IRtChannelHttpServer;
class IRtChannelSink;
class IRtChannelServerAcceptor;
class IRtChannelServerSink;

class CRtHttpUrl;
class CRtHttpProxyInfo;
class CRtMessageBlock;
class CRtInetAddr;
class CRtString;

class RT_API_EXPORT CRtChannelManager
{
public:
	static CRtChannelManager* Instance();

	typedef DWORD CFlag;
	enum { 
		CFLAG_SEND_NO_PARTIAL_DATA = (1 << 0),
		CFLAG_WITH_BROWER_PROXY = (1 << 1)
	};

	/// Create <IRtChannelHttpClient> for HTTP client.
	RtResult CreateChannelHttpClient(
		IRtChannelHttpClient *&aClient,
		CRtHttpUrl *aURL, 
		CFlag aFlag);

	RtResult CreateChannelHttpClientWithProxy(
		IRtChannelHttpClient *&aClient,
		CRtHttpUrl *aURL, 
		CRtHttpProxyInfo *aPi);

	/// Create <IRtAcceptor> for HTTP server.
	RtResult CreateHttpAcceptor(
		IRtChannelServerAcceptor *&aAcceptor,
		CFlag aFlag);

	RtResult CreateUrl(CRtHttpUrl *&aUrl, const CRtString &aSepc);

/*	class CNotifyBuffer 
	{
	public:
		CNotifyBuffer(DWORD aFlag, LPCSTR aMsg)
			: m_dwFlag(aFlag), m_pszMsg(aMsg)
		{
		}

		DWORD m_dwFlag;
		LPCSTR m_pszMsg;
	};

	RtResult RegisterHttpProxyNotifaction(IRtObserver *aObserver);

	RtResult SetHttpProxyServerAddress(LPCSTR aIp, WORD aPort, DWORD aType);

	RtResult SetHttpProxyUsernameAndPassword(
		LPCSTR pszUserName, 
		LPCSTR pszPassword);
*/
private:
	CRtChannelManager();

	static CRtChannelManager s_rtChannelManagerSingleton;
};

class /*RT_API_EXPORT*/ IRtChannel : public IRtTransport
{
public:
	/// Begin SendPrivateData().
	virtual RtResult AsyncOpen(IRtChannelSink *aSink) = 0;

	/// Get URL such as 'http://...'
	virtual RtResult GetUrl(CRtHttpUrl *&aUrl) = 0;

protected:
	virtual ~IRtChannel() { }
};

class /*RT_API_EXPORT*/ IRtChannelSink : public IRtTransportSink
{
public:
	/// Channel is connected.
	virtual void OnConnect(RtResult aReason, IRtChannel *aChannelId) = 0;

protected:
	virtual ~IRtChannelSink() { }
};

class /*RT_API_EXPORT*/ IRtChannelHttpClient : public IRtChannel
{
public:
	/// Set request info before sending request.
	virtual RtResult SetOrAddRequestHeader(
		const CRtString &aHeader, 
		const CRtString &aValue) = 0;

	/// Set request info before sending request.
	virtual RtResult SetRequestMethod(const CRtString &aMethod) = 0;

	virtual RtResult SetPath( const CRtString& aPath ) = 0;

	/// Get request info after SetRequestMethod.
	virtual RtResult GetRequestMethod(CRtString &aMethod) = 0;

	/// Get response info after IRtChannelSink::OnStartChannel.
	virtual RtResult GetResponseStatus(LONG &aStatus) = 0;

	/// Get response info after IRtChannelSink::OnStartChannel.
	virtual RtResult GetResponseHeader(
		const CRtString &aHeader, 
		CRtString &aValue) = 0;
	
protected:
	virtual ~IRtChannelHttpClient() { }
};

class /*RT_API_EXPORT*/ IRtChannelHttpServer : public IRtTransport
{
public:
	/// Set response info before sending response.
	virtual RtResult SetOrAddResponseHeader(
		const CRtString &aHeader, 
		const CRtString &aValue) = 0;

	/// Set response info before sending response.
	virtual RtResult SetResponseStatus(
		DWORD aStatus, 
		const CRtString &aText) = 0;

	/// Get request info after IRtChannelSink::OnDataArrival.
	virtual RtResult GetRequestMethod(CRtString &aMethod) = 0;

	/// Get request info after IRtChannelSink::OnDataArrival.
	virtual RtResult GetRequestHeader(
		const CRtString &aHeader, 
		CRtString &aValue) = 0;

	/// Get request info after IRtChannelSink::OnDataArrival.
	virtual RtResult GetRequestPath(CRtString &aPath) = 0;

	/***********************************************************************************
	 * Function: GetUploadFileInfo()
	 * Description: User agent can upload file data to http server via posting FORMs with 
	 *   <multipart/form-data> ENCTYPE attribute. This function is to parse the submitted
	 *   data and pick out the uploaded file name and content. The file is specified by the 
	 *   input tag of file type in the form.
	 * Parameters:
	 * 	 inData: input data that http server receives;
	 * 	 inInputTagName: input input tag's name in the form, which specifies the file being uploaded;
	 * 	 outFileName: output name of the uploaded file, which may be empty if it is not supplied;
	 * 	 outFileContent: output content of the uploaded file;
	 * Return: 
	 * 	 RT_OK - successfully;
	 * 	 RT_ERROR_FAILURE - something wrong, for detail error info see logs.
	 ***********************************************************************************/
	virtual RtResult GetUploadFileInfo(
		CRtMessageBlock& inData, 
		const CRtString& inInputTagName, 
		CRtString& outFileName, 
		CRtString& outFileContent) = 0;

	virtual IRtTransport* GetTcpTransport() = 0;

	virtual RtResult PrepareResponse(CRtMessageBlock& data) = 0;
	virtual RtResult Response() = 0;

protected:
	virtual ~IRtChannelHttpServer() { }
};

class /*RT_API_EXPORT*/ IRtChannelServerAcceptor : public IRtReferenceControl
{
public:
	virtual RtResult StartListen(
		IRtChannelServerSink *aSink,
		const CRtInetAddr &aAddrListen) = 0;

	virtual RtResult StopListen(RtResult aReason) = 0;

protected:
	virtual ~IRtChannelServerAcceptor() {}
};

class /*RT_API_EXPORT*/ IRtChannelServerSink
{
public:
	/// Channel of server is created.
	/// You should invoke AsyncOpen() in this function.
	virtual void OnServerCreation(IRtChannelHttpServer *aServer) = 0;

protected:
	virtual ~IRtChannelServerSink() { }
};

#endif // !RTHTTPINTERFACE_H
